package com.bh.common.utils.uuid;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.bh.common.utils.spring.SpringUtils;
import com.github.yitter.contract.IdGeneratorOptions;
import com.github.yitter.idgen.YitIdHelper;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * ID生成器工具类
 *
 * @author ruo-yi
 */
public class IdUtils {

    /**
     * 获取随机UUID
     *
     * @return 随机UUID
     */
    public static String randomUUID() {
        return UUID.randomUUID().toString();
    }

    /**
     * 简化的UUID，去掉了横线
     *
     * @return 简化的UUID，去掉了横线
     */
    public static String simpleUUID() {
        return UUID.randomUUID().toString(true);
    }

    /**
     * 获取随机UUID，使用性能更好的ThreadLocalRandom生成UUID
     *
     * @return 随机UUID
     */
    public static String fastUUID() {
        return UUID.fastUUID().toString();
    }

    /**
     * 简化的UUID，去掉了横线，使用性能更好的ThreadLocalRandom生成UUID
     *
     * @return 简化的UUID，去掉了横线
     */
    public static String fastSimpleUUID() {
        return UUID.fastUUID().toString(true);
    }

    /**
     * 1-漂移算法，2-传统算法
     */
    final static short method = 1;
    public static final IdGeneratorOptions OPTIONS = new IdGeneratorOptions();

    public static Long getNextId() {
        ShortIdUtils shortIdUtils = SpringUtils.getBean(ShortIdUtils.class);
        return shortIdUtils.generate();
    }

    /**
     * 获取多个ID
     *
     * @param size
     * @return
     */
    public static List<Long> getManyNextId(int size) {
        ShortIdUtils shortIdUtils = SpringUtils.getBean(ShortIdUtils.class);
        List<Long> idList = Collections.synchronizedList(new ArrayList<>());
        for (int i = 0; i < size; i++) {
            idList.add(shortIdUtils.generate());
        }
        return idList;
    }

    public static Long getSnowNextId() {
        OPTIONS.Method = method;
        OPTIONS.WorkerId = 2;
        // 首先测试一下 IdHelper 方法，获取单个Id
        YitIdHelper.setIdGenerator(OPTIONS);
        return YitIdHelper.nextId();
    }

    /**
     * 获取多个ID
     *
     * @param size
     * @return
     */
    public static List<Long> getManySnowNextId(int size) {
        List<Long> idList = Collections.synchronizedList(new ArrayList<>());
        int poolSize = Math.max(size, 100);
        //-------------线程开始---------------
        // 启用多线程
        ThreadFactory idUtilsFactory = new ThreadFactoryBuilder().setNamePrefix("idUtilsFactory").build();
        ExecutorService executor = new ThreadPoolExecutor(100, poolSize, 10, TimeUnit.SECONDS, new SynchronousQueue<>(), idUtilsFactory);
        CountDownLatch countDownLatch = new CountDownLatch(size);
        for (int i = 0; i < size; i++) {
            Runnable run = () -> {
                try {
                    idList.add(IdUtils.getNextId());
                } catch (Exception ignored) {
                }
                synchronized (Runnable.class) {
                    countDownLatch.countDown();
                }
            };
            executor.execute(run);
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
        } finally {
            executor.shutdown();
        }
        return idList;
    }


    public static String getRandomPwd() {    //static修饰，可以不用创建对象，直接使用该方法。
        Random r = new Random();
        ArrayList<Character> pwlist = new ArrayList<Character>();
        for (int i = 0; i < 10; i++) {
            if (i < 3) {
                //依次生成3个数字，放在list里
                char num = (char) (48 + r.nextInt(10));   //ASCII码十进制代码48-57代表数字0-9
                pwlist.add(num);
            } else if (i < 6) {
                //依次生成3个大写字母，放在list里
                char upper = (char) (65 + r.nextInt(26)); //ASCII码十进制代码65-90代表大写字母A-Z
                pwlist.add(upper);
            } else if (i < 9) {
                //依次生成3个小写字母，放在list里
                char lower = (char) (97 + r.nextInt(26)); //ASCII码十进制代码97-122代表小写字母a-z
                pwlist.add(lower);
            } else {
                //最后一位生成‘@’，放在list里
                pwlist.add((char) (64));               //ASCII码十进制代码64代表‘@’
            }
        }
        //乱序
        Collections.shuffle(pwlist);
        StringBuilder str = new StringBuilder();
        pwlist.forEach(str::append);
        return str.toString();
    }
}
